import { useCallback, useEffect, useMemo, useRef, useState } from "react";
import type { Lyric } from "lrc-kit";
import { motion, useMotionValue, useScroll } from "motion/react";
import {
  useMouse,
  useDrop,
  useEventListener,
  useUpdateEffect,
  useClickAway,
  useSize,
} from "ahooks";
import { Input } from "antd";
import { useWhyDidYouUpdate, useMemoizedFn } from "ahooks";
function LyricItem({
  lyric,
  scale,
  onChange,
  index,
}: {
  lyric: Lyric;
  scale: number;
  onChange: (val: Lyric, index: number) => void;
  index: number;
}) {
  const devRef = useRef(null);
  useWhyDidYouUpdate("Ruler", [lyric, scale, onChange, index]);
  const height = 42;
  const top = useCallback(
    (currentTime: number) => {
      return currentTime * scale - height / 2;
    },
    [scale]
  );
  const y = useMotionValue(top(lyric.timestamp));
  const [isEdit, setIsEdit] = useState(false);
  useUpdateEffect(() => {
    y.set(top(lyric.timestamp));
  }, [scale]);
  useClickAway(() => {
    setIsEdit(false);
  }, devRef);
  return (
    <>
      <motion.div
        ref={devRef}
        drag="y"
        dragMomentum={false}
        initial={{
          x: 80,
        }}
        style={{ y, height, transformOrigin: "left" }}
        whileHover={{ scale: 1.08 }}
        onDoubleClick={() => {
          setIsEdit(true);
        }}
        className="flex  items-center border border-orange-300 px-4 text-orange-300 rounded-full absolute hover:shadow-md hover:shadow-white/15 hover:cursor-move text-sm "
        onDragEnd={() => {
          onChange(
            { ...lyric, timestamp: y.get() / scale + height / 2 / scale },
            index
          );
        }}
        onDrag={() => {
          onChange(
            { ...lyric, timestamp: y.get() / scale + height / 2 / scale },
            index
          );
        }}
      >
        {isEdit ? (
          <Input
            value={lyric.content}
            autoFocus
            onChange={(e) => {
              onChange({ ...lyric, content: e.target.value }, index);
            }}
            onBlur={() => setIsEdit(false)}
          />
        ) : (
          `${lyric.content} ${lyric.timestamp.toFixed(2)}`
        )}

        <div className="h-[1px] bg-slate-200/50 w-[88px] absolute top-[20px] -left-[86px]"></div>
      </motion.div>
    </>
  );
}

interface PropsInt {
  duration: number;
  currentTime: number;
  updateCurrentTime: (val: number) => void;
  scale: number;
  lyric: Lyric[];
  onChange: (lyric: Lyric[]) => void;
}

export default function Ruler({
  duration,
  currentTime,
  updateCurrentTime,
  scale,
  lyric,
  onChange,
}: PropsInt) {
  useWhyDidYouUpdate("Ruler", [
    duration,
    currentTime,
    updateCurrentTime,
    scale,
    lyric,
    onChange,
  ]);
  const rulerRef = useRef(null);
  const ruleWrapRef = useRef(null);
  const { scrollY } = useScroll({ container: ruleWrapRef });
  const height = useMemo(() => {
    return duration * scale + 4 + "px";
  }, [duration, scale]);

  const sliderHeight = useMemo(() => {
    return currentTime * scale + "px";
  }, [currentTime, scale]);

  const musicSliderRef = useRef<HTMLDivElement>(null);
  const { elementY } = useMouse(musicSliderRef.current);

  useEventListener(
    "scroll",
    (e) => {
      e.preventDefault();
    },
    {
      target: document.body,
    }
  );

  const onChangeLyricConent = useMemoizedFn((content: Lyric, index: number) => {
    onChange(
      lyric.map((item, cindex) => {
        if (cindex === index) return { ...content };
        return { ...item };
      })
    );
  });

  const size = useSize(ruleWrapRef);

  useEffect(() => {
    if (size?.height) {
      (ruleWrapRef.current as unknown as Element).scroll({
        top: parseInt(sliderHeight) - scale,
        // behavior: "smooth",
      });
    }
  }, [sliderHeight, size, scrollY, ruleWrapRef, scale]);

  return (
    <div className="w-full h-full overflow-auto" ref={ruleWrapRef}>
      <div
        className="w-[10px] bg-white rounded-lg p-[2px] relative"
        style={{ height: height }}
        ref={musicSliderRef}
      >
        <div
          onClick={() => {
            const current = elementY / scale;
            updateCurrentTime(current);
          }}
        >
          <div
            className="w-full bg-orange-400 rounded-lg cursor-pointer"
            style={{ height: sliderHeight }}
          ></div>
          <motion.div
            ref={rulerRef}
            className="w-full h-full flex flex-col absolute top-0 left-[15px] z-20 cursor-pointer"
          >
            {Array.from({ length: parseInt(height) / scale }).map(
              (_, wrapIndex) => {
                return (
                  <div
                    key={wrapIndex}
                    className="w-[10px]  text-white text-sm flex flex-col relative"
                    style={{ height: scale }}
                  >
                    {Array.from({ length: 10 }).map((_, index) => {
                      const ci = index + 1;
                      return (
                        <div
                          key={index}
                          className="h-[10%] border-t-[1px]  absolute left-0 hover:hover:border-t-[2px] border-[#fff] transition-[border] box-border "
                          style={{
                            top: ci * (scale / 10),
                            width:
                              ci === 5 ? "15px" : ci === 10 ? "20px" : "10px",
                          }}
                        >
                          {ci === 10 ? (
                            <span className="text-white absolute block text-sm left-[24px] w-[30px] text-left -top-[10px]">
                              {wrapIndex + 1}s
                            </span>
                          ) : null}
                        </div>
                      );
                    })}
                  </div>
                );
              }
            )}
          </motion.div>
        </div>
        <div className="w-[220px] h-full absolute left-[0px] top-0">
          {lyric.map((item, index) => {
            return (
              <LyricItem
                lyric={item}
                scale={scale}
                key={index}
                index={index}
                onChange={onChangeLyricConent}
              ></LyricItem>
            );
          })}
        </div>
      </div>
    </div>
  );
}
